#ifndef CRENDERTARGETOGL_H_INCLUDED
#define CRENDERTARGETOGL_H_INCLUDED

#include "IRenderTarget.h"


/// The OpenGL Render Target Interface
/* For more detail read IRenderTarget.h */
class CRenderTargetOGL : public IRenderTarget {
friend class IRenderTarget;
protected:
private:
	uint m_uiFrameBufferHandleOGL;			///< OpenGL Framebuffer handle
	uint m_uiTextureHandleOGL;					///< OpenGL Texture handle (representation of the framebuffer above, but as texture)
	uint m_uiRenderBufferDepthHandleOGL;	///< OpenGL Depth component. Used only if both color and depth formats are specified

public:
	// These functions render using the queue:
	void Enqueue	( IInstance* 	instance, 	IRenderable* model );
	void Enqueue	( IInstance* 	instance 	);
	void Enqueue	( IRenderable* model 		);
	// These functions render directly:
	void Render		( IInstance* 	instance, 	IRenderable* model );
	void Render		( IInstance* 	instance 	);
	void Render		( IRenderable* model 		);

	// These will clear the render target:
	void Clear				( );
	void Clear				( crgba &color );
	// This will refresh your screen if the render target is your backbuffer:
	void Present			( handle hwnd );
	// This will process the local queue. You can either clear the queue, or keep it for later:
	void Process			( );
	void ProcessAndKeep	( );
	// This will reset the queue:
	void ResetQueue		( );

	// Some helper functions for projecting and unprojecting geometry and points from camera space to world space and vice versa
	vec3r Project			( cvec3r &point );
	vec3r Unproject		( cvec3r &point );
	void 	ProjectBatch	( vec3r** destination, cvec3r *points, cui32 count );
	void 	UnprojectBatch	( vec3r** destination, cvec3r *points, cui32 count );

	// Advanced drawing functions. You can use them on your own, but i'd rather use the Process() routine (if you are using the queue) or the automated Render(...) functions above.
	void SetVertexFormat	( culong &format );
	void SetStateLighting( bool flag );
	void SetStateCulling	( eCULL_STATE flag );
	void SetStateDepth	( bool flag );
	void SetCamera			( IInstance* cam );
	void SetPerspective	( const sCameraData &data );
	void SetOrtho			( cint &width, cint &height );
	void SetView			( cvec3r &pos, cvec3r &view, cvec3r &up );
	void SetView			( IInstance* instance );
	void SetEffect			( IEffect* eff );
	void SetTransform		( IInstance* instance );
	void SetShader			( IShader* shader );
	void SetLight			( cint i, IInstance* lightinst, 	const sLightData &lightdata );
	void SetFog				( crgba &color, cint mode, creal start, creal end, creal density );

	// Tell the video adapter to prepare for drawing
	void Begin( );
	// Simple function to render any vertex data from a float array
	void RenderPrimitiveUserPointer( cuint type, cuint count, handle data, cuint stride );
	// These are primitive drawing functions
	void BeginPrimitive( VERTEX_PRIMITIVE_TYPE primitive_type );
	void RenderVertex( cvec3r &point );
	void RenderVertex( cvec3r &point, cvec2r &uv );
	void RenderVertex( cvec3r &point, cvec2r &uv, crgba &color );
	void RenderVertex( cvec3r &point, crgba &color );
	void RenderVertex( cvec3r &point, cvec2r &uv, crgba &color, cvec3r &normal );
	void EndPrimitive( );
	// Tell the video adapter that we are ready with the render target and stop it
	void End	( );

	// This one comes from ITexture. Binds this Render Target as simple texture. Works only when not drawing in it!
	void Bind( ui16 stage = 0 );


			    // Constructor & Destructor
			    CRenderTargetOGL( int w, int h );
			    CRenderTargetOGL( int w, int h, byte* data, int color_format = eTF_RGB24, int depth_format = eTF_JUST_DONT, int flags = eDBF_DEFAULT_SETTINGS );
				~CRenderTargetOGL( );
};


#endif // CRENDERTARGETOGL_H_INCLUDED
